package SIM_nodeInfo;

require Exporter;
use strict;
use SIM_base;
use SIM_cgiSettings;
use SIM_settings;
use SNMP_util;

# Settings module for shared perl settings.
our @ISA        = ("Exporter");
our @EXPORT     = qw(
		     testNodeStatus dispNodeStatus dispHostName printNodeLine getMacAddr getNetName displayOui getLoggingInfo getSwitchPort
                     getDispIntSpeed getMngtContext dispColorTable
                    );
our @VERSION    = 0.01;                 # version number

my $sharedConfDir = $ENV{'SIM_SHAREDCONFD'} || die "Oops no env found for SIM_SHAREDCONFD.";
my $macDatabase = $ENV{'SIM_MACDATAB'} || die "Oops no env found for SIM_MACDATAB.";


# exported color settings.
sub getMngtContext {
  my $ipAddr = "@_[0]";
  my $ipDir = getIpDir( $ipAddr );
  if (( -f "$ipDir/vendor" ) and ( -f "$ipDir/hostname.txt" )) {
    my $vendor = catFileLine("$ipDir/vendor");
    my $hostName = catFileLine("$ipDir/hostname.txt");
    my ( $shortName, $rest ) = split('\.', $hostName);
    my $managementContext = catFileLine("$SIMparam{'SIMdeviceDir'}/$vendor/$shortName/mngtContext");
    return $managementContext;
  }
}

sub dispColorTable {
  print("<H3>Node table</H3>");
  print("<TABLE>");
  while ( my ($key, $value) = each(%nodeColor)) {
    print("<TR><TD BGCOLOR=$nodeColor{$key}>$key</TD><TD>$nodeDescription{$key}</TD></TR>");
  }
  print("</TABLE>");
}

sub getDispIntSpeed {
  my $ipAddr = "@_[0]";
  my $SNMPSTR = "@_[1]";
  my $intRef = "@_[2]";
  my $intName = "@_[3]";
  my $ipDir = getIpDir($ipAddr);
  my $oidVendor = catFileLine("$ipDir/vendor");
  my $dIntSpeed;
  my $intSpeed = &snmpget("$SNMPSTR", "1.3.6.1.2.1.2.2.1.5.$intRef");
  if ( $intSpeed >= 1000000000 ) {
    $dIntSpeed = sprintf("%.0f",$intSpeed / 1000000000) . " Gbps";
  } elsif ( $intSpeed >= 1000000 ) {
    $dIntSpeed = sprintf("%.0f",$intSpeed / 1000000) . " Mbps";
  } elsif ( $intSpeed >= 1000 ) {
    $dIntSpeed = sprintf("%.0f",$intSpeed / 1000) . " Kbps";
  } else {
    $dIntSpeed = "$intSpeed bps";
  }
  if (( "$intSpeed" eq "0" ) or ( "$intSpeed" eq "4294967295" )) {
    $intSpeed = "";
    if ( $oidVendor eq "cisco" ) {
      if ( substr($intName, 0, 3) eq "ATM" ) { $intSpeed = 155000000; $dIntSpeed = "auto 155 Mbps"; }
      elsif ( substr($intName, 0, 2) eq "Te" ) { $intSpeed = 10000000000; $dIntSpeed = "auto 10 Gbps"; }
    }
    if ( "$intSpeed" eq "" ) { $intSpeed = 10000000000; $dIntSpeed = "default 10 Gbps"; }
  }
  return( $intSpeed, $dIntSpeed );
}

sub getLoggingInfo {
  my $ipAddr = "@_[0]";
  my %testEntry = ();
  my $ipDir = getIpDir( $ipAddr );
  my $firstMac = catFileLine("$ipDir/firstmac.txt");
  my @ipEntries = <$SIMparam{'SIMmacDatab'}/$firstMac/ipint-*.txt>;
  foreach my $entry (@ipEntries) {
    my $info = catFileLine( $entry );
    my ( $ipAddr, $rest ) = split(' ', $info);
    print("<!-- getDnsPtr: $ipAddr. ");
    my $deviceName = getDnsPtr( $ipAddr );
    print("-->");
    if ( "$deviceName" ne "" ) {
      $testEntry{$deviceName} = 1;
    }
    $testEntry{$ipAddr} = 1;
  }
  if ( -d $SIMparam{'SIMsyslogDir'} ) {
    chdir $SIMparam{'SIMsyslogDir'};
    my @syslogDir = <*>;
    my $info;
    my $reportLog;
    # show the newest date first
    my @revSyslogDir = reverse(@syslogDir);
    foreach my $entry (@revSyslogDir) {
      foreach my $testItem (keys %testEntry) {
#       print("<TR><TD COLSPAN=9>Testing $entry/$testItem/all-messages</TD></TR>");
        if ( -f "$SIMparam{'SIMsyslogDir'}/$entry/$testItem/all-messages" ) {
          $info = ` tail -n 5 $SIMparam{'SIMsyslogDir'}/$entry/$testItem/all-messages `;
          $info =~ s/\n/<BR>/g;
          return( $testItem, $entry, $info );
          last;
        }
      }
      if ( "$info" ne "" ) {
        $reportLog = $entry;
        last;
      }
    }
  }
}


sub displayOui {
  my $macAddr = "@_[0]";
  my $ouiMac = substr($macAddr, 0, 8);
  my $vendor = catFileLine("$SIMparam{'SIMmacOuiDir'}/$ouiMac/vendor");
  if ( $vendor eq "" ) {
    $vendor = "undefined";
  }
  return("(<A HREF=$httpScriptName?mon+updateOui+$ouiMac>$vendor</A>)");
}

sub testHwStatusColor {
  # test if the hw status is oke.
  my $ipAddr = "@_[0]";
  my $returnColor = "@_[1]";
  my $ipDir = getIpDir( $ipAddr );
  if (( -f "$ipDir/vendor" ) and ( -f "$ipDir/hostname.txt" )) {
    my $vendor = catFileLine("$ipDir/vendor");
    my $hostName = catFileLine("$ipDir/hostname.txt");
    my $shortName = shortHostname($hostName);
    my $devDir = "$SIMparam{'SIMdeviceDir'}/$vendor/$shortName";
#   print("<TD>$hostName $devDir</TD>");
    if ( -f "$devDir/hwMonInfo" ) {
      if ( $returnColor ne "#00FF33" ) {
        # if the device is not normal, and the hwMon is active set the base status to dark-green
        $returnColor = "#00BBBB";
      }
      my @statusEntries = <$devDir/status-*>;
      if ( "$statusEntries[0]" ne "" ) {
        foreach my $statEntry (@statusEntries) {
          my ( $prefix, $oid ) = split('status-', $statEntry);
          if ( ! -f "$devDir/statusConfirmed-$oid" ) {
            $returnColor = "#D08A4D"; # hwmonColor
            last;
          }
        }
      }
#   } else {
#     print("<TD>noHwMon $ipAddr</TD>");
    }
# } else {
#   print("<TD>noDev $ipAddr</TD>");
  }
  return( $returnColor );
}

sub testNodeStatus {
  my $ipAddr = "@_[0]";

  my $ipDir = getIpDir( $ipAddr );
  my $macAddr;
  my $nodeUp = 0;
  my $nodeDown = 0;
  my $nodeSlow = 0;
  my $nodeConfirmed = 0;

  my $statusColor = "#CCCCCC";
  if ( -f "$ipDir/firstmac.txt" ) {
    $macAddr = catFileLine("$ipDir/firstmac.txt");
  }
  if ( "$ipAddr" eq "" ) {
    $statusColor = "brown";
  } elsif ( "$macAddr" eq "" ) {
    printDebug("1", "testNodeStatus: no mac found for $ipAddr.");
  } elsif ( ! -d "$macDatabase/$macAddr" ) {
    printDebug("1", "testNodeStatus: no macdir found for $ipAddr $macDatabase/$macAddr).");
  } else {
    my @intList = <$macDatabase/$macAddr/ipint-*>;
    foreach my $ipInt (@intList) {
      my $intInfo = catFileLine("$ipInt");
      my ( $intIpAddr, $rest ) = split(' ', $intInfo);
      my $ipDir = getIpDir( $intIpAddr );
      my $pollStatus = catFileLine("$ipDir/pollstatus.txt");
      my ( $rest, $status ) = split(' ', $pollStatus);
#     print(" $intIpAddr=$status ");
      if ( "$status" eq "Up" ) {
        $nodeUp++;
      } elsif ( "$status" eq "Down" ) {
        $nodeDown++;
      } elsif ( "$status" eq "Slow" ) {
        $nodeSlow++;
      } elsif ( "$status" eq "Confirmed" ) {
        # test only for confirmed nodes if it is a stable ip.
        my $manType = catFileLine("$ipDir/managementtype.txt");
        if ( $manType ne "unstable" ) {
          $nodeConfirmed++;
        }
      }
    }
    if ( "$nodeSlow" ne 0 ) {
      $statusColor = "#FF9966"; #Slow
    } elsif (( "$nodeUp" eq 0 ) and ( "$nodeDown" eq 0 )) {
      if ( $nodeConfirmed ne 0 ) {
        $statusColor = "#DDA0DD"; #purple (confirmed)
      } else {
        # all down, not confirmed
        $statusColor = "#66FFFF"; #bleu
      }
      # test the hw status.
      $statusColor = &testHwStatusColor($ipAddr, $statusColor); 
    } elsif ( "$nodeUp" eq 0 ) {
      $statusColor = "#FF0033"; #red
    } elsif ( "$nodeDown" eq 1 ) {
      $statusColor = "#FFFF33"; #yellow
    } elsif ( "$nodeDown" ne 0 ) {
      $statusColor = "#FFCC33";  #orange
    } else {
#     print("<TD BGCOLOR=$statusColor>$ipAddr</TD>");
      $statusColor = &testHwStatusColor($ipAddr, "#00FF33"); #green
    }
    printDebug("1", "testNodeStatus ipAddr=$ipAddr, macAddr=$macAddr, nodeUp=$nodeUp, nodeDown=$nodeDown.");
  }
  if ( "$statusColor" eq "#CCCCCC" ) {
    # if no mac ip's found, return the current status for the IP
    my $pollInfo = catFileLine("$ipDir/pollstatus.txt");
    my ( $statusTime, $pollStatus ) = split(" ", $pollInfo);
    if ( "$ipColor{ $pollStatus}" ne "" ) {
      $statusColor = $ipColor{$pollStatus};
    }
  }
# return ( "$statusColor mac:$macAddr,U:$nodeUp,D:$nodeDown,S:$nodeSlow,C:$nodeConfirmed" );
  return ( "$statusColor" );
}

sub dispNodeStatus {
  my $ipAddr = "@_[0]";
  my $return = "@_[1]";
  my ( $statusTime, $pollStatus, $dispDate, $dispColor );
  my $ipDir = getIpDir($ipAddr);
  if ( -d $ipDir ) {
    my $pollInfo = catFileLine("$ipDir/pollstatus.txt");
    ( $statusTime, $pollStatus ) = split(" ", $pollInfo);
    $dispDate = substr($statusTime, 0, 10);
    my $now = time;
    my $testDate = printDate( $now, "yyyymmdd" );
    if ( "$testDate" eq "$dispDate" ) {
      $dispDate = substr($statusTime, 11);
    }
    $dispColor = $ipColor{$pollStatus};
  } else {
    $dispColor = "#DDDDDD";
    $dispDate = "not defined"
  }
  my $msg = "<TD BGCOLOR=$dispColor ALIGN=center><A HREF=$httpScriptName?mon+nodestatus+$ipAddr>$dispDate</A></TD>";
  if ( $return eq "return" ) {
    return $msg;
  } else {
    print("$msg");
  }
}

sub dispHostName {
  # this will display the hostname (based on what is available).
  my $ipAddr = "@_[0]";
  my $return = "@_[1]";
  my $bgColor = "@_[2]";
  my $ipDir = getIpDir($ipAddr);
  my $devName;
  my ( $macAddr, $macType ) = &getMacAddr($ipAddr);
  if ( -f "$ipDir/manHostname" ) {
    $devName = catFileLine("$ipDir/manHostname");
  } elsif ( -f "$ipDir/hostname.txt" ) {
    $devName = catFileLine("$ipDir/hostname.txt");
  } elsif ( -f "$ipDir/hwName" ) {
    $devName = catFileLine("$ipDir/hwName");
  } elsif ( -f "$ipDir/dhcpname.txt" ) {
    $devName = catFileLine("$ipDir/dhcpname.txt");
  } elsif ( -f "$ipDir/hostname-cdp" ) {
    $devName = catFileLine("$ipDir/hostname-cdp");
  } elsif ( -f "$SIMparam{'SIMmacDatab'}/$macAddr/acsHostname" ) {
    $devName = catFileLine("$SIMparam{'SIMmacDatab'}/$macAddr/acsHostname");
  }
  if ( $return eq "return" ) {
    return "<TD BGCOLOR=$bgColor>$devName</TD>";
  } elsif ( $return eq "data" ) {
    return "$devName";
  } else {
    print("<TD>$devName</TD>");
    return "<TD>$devName</TD>";
  }
}

sub getNetName {
  my $ipAddr = "@_[0]";
  my $dispOpt = "@_[1]";
  my $printUrl = "@_[2]";
  my $ipDir = &getIpDir( $ipAddr );
  my ( $shortName, $netName, $longNet );
  if ( -f "$ipDir/network" ) {
    my $network = catFileLine("$ipDir/network");
    $longNet = longIp($network);
    open(IN, "$SIMparam{'SIMsubnetDir'}/net-$longNet");
    my @lines = <IN>;
    close IN;
    foreach my $entry (@lines) {
      my ( $type, $rest ) = split(' ', $entry, 2);
      if ( $type eq "SHORTNAME:" ) {
        $shortName = $rest;
        chomp $shortName;
      } elsif ( $type eq "NAME:" ) {
        $netName = $rest;
        chomp $netName;
      }
    }
  }
  if ( $netName ne "" ) {
    if ( $dispOpt eq "short" ) {
      $netName = $shortName;
    } else {
      $netName = "$shortName, $netName";
    }
    if ( $printUrl ne "csv" ) {
      $netName = "<A HREF=$httpScriptName?subnet2+listNodes+net-$longNet>$netName</A>";
    }
    return($netName);
  }
}

sub getMacAddr {
  # general tool to find the mac addr for an node.
  my $ipAddr = "@_[0]";
  my $ipDir = getIpDir($ipAddr);
  my ( $macAddr, $macType );
  if ( -f "$ipDir/dhcpmacaddr.txt" ) {
    $macAddr = catFileLine("$ipDir/dhcpmacaddr.txt");
    $macType = "dhcp";
  } elsif ( -f "$ipDir/snmpmac.txt" ) {
    $macAddr = catFileLine("$ipDir/snmpmac.txt");
    $macType = "snmp";
  } elsif ( -f "$ipDir/arpmac.txt" ) {
    $macAddr = catFileLine("$ipDir/arpmac.txt");
    $macType = "arp";
  }
  return( $macAddr, $macType );
}

sub getSwitchPort {
  my $macAddr = "@_[0]";
  my $format = "@_[1]";
  my $switchInfo;
  my @switchRecs = <$macDatabase/$macAddr/switchport-*>;
  # first sort on date, then process / cleanup.
  my @entries = ();
  foreach my $entry (@switchRecs) {
    my $size = -s $entry;
    if ( $size eq 0 ) {
      printDebug( 1, "getSwitchPort: removing empty file $entry");
      unlink($entry);
    } else {
      my $time = (stat $entry)[9];
      splice @entries, @entries, 0, "$time $entry"; #Opbouwen array met datum num plus filename.
    }
  }
  my $cleanTime;
  @entries = reverse(sort(@entries)); #sorteren, nieuwste entry eerst
  foreach my $entry (@entries) {
    my ( $time, $file ) = split(' ', $entry);
    my $switchPortInfo = catFileLine($file);
    if (( $cleanTime eq "" ) and ( $time ne "" )) {
      # set clean time to more then 3 days after the newest switch info file.
      $cleanTime = $time - 300000;
      my $printDate = printDate($cleanTime);
      printDebug(1, "getSwitchPort: cleanTime = $cleanTime, $printDate switchPortInfo = $switchPortInfo");
    }
    my ( $switchName, $rest ) = split(' ', $switchPortInfo, 2);
    my ( $switchport, $description ) = split(' \(', $rest, 2);
    my $formatIntName = &formatIntName($switchport);
    if ( $switchport eq "" ) {
      # remove old definition files
      printDebug( 1, "getSwitchPort: $macAddr switchport = \"$switchport\", switchPortInfo = $switchPortInfo");
      unlink($file);
    } elsif (( $cleanTime ne "" ) and ( $time < $cleanTime )) {
      printDebug( 1, "getSwitchPort: $macAddr cleanTime = $cleanTime, time = $time, switchPortInfo = $switchPortInfo");
      unlink($file);
    } elsif ( ! -f "$SIMparam{'SIMswitchDevices'}/$switchName/macCount-$formatIntName" ) {
      printDebug( 1, "getSwitchPort: $macAddr no $SIMparam{'SIMswitchDevices'}/$switchName/macCount-$formatIntName, switchPortInfo = $switchPortInfo");
      # remove if not defined as an interface
      unlink($file);
    } elsif ( -f "$SIMparam{'SIMswitchDevices'}/$switchName/trunk-$formatIntName" ) {
      printDebug( 1, "getSwitchPort: $macAddr trunk $SIMparam{'SIMswitchDevices'}/$switchName/trunk-$formatIntName, switchPortInfo = $switchPortInfo");
      unlink($file);
    } else {
      my $dispDate = printDate($time);
      if ( $switchInfo eq "" ) {
        if ( $format eq "link" ) {
          $switchInfo = "$dispDate <A HREF=$httpScriptName?switch2+displaySwitch+$switchName>$switchName</A> $switchport ($description";
        } else {
          $switchInfo = "$switchPortInfo";
        }
      } else {
        if ( $format eq "link" ) {
          #<A HREF=$httpScriptName?mon+updateOui
          $switchInfo = "$switchInfo<BR>$dispDate <A HREF=$httpScriptName?switch2+displaySwitch+$switchName>$switchName</A> $switchport ($description";
        } elsif ( $format eq "html" ) {
          $switchInfo = "$switchInfo<BR>$switchPortInfo";
        } else {
          $switchInfo = "$switchInfo, $switchPortInfo";
        }
      }
    }
  }
  return $switchInfo;
}

sub printNodeLine {
  my $ipAddr = "@_[0]";
  my $return = "@_[1]";
  my ( $nodeType, $pollStatus, $macAddr, $macDispColor, $manType, $snmpColor, $dnsName, $ipIntNo, $l2IntNo, $switchPort,
       $rest, $statusTime, $dispDate, $dnsType, $dnsHost, $dnsDomain, $recType, $oidName );
  my $ipDir = getIpDir($ipAddr);
  if ( ! -d $ipDir ) {
    $macAddr = "not defined";
  } else {
    my $dnsInfo = catFileLine("$ipDir/dnsname.txt");
    ( $dnsType, $dnsHost, $dnsDomain ) = split (' ', $dnsInfo);
    $dnsName = "$dnsHost.$dnsDomain";
    my $macType;
    ( $macAddr, $macType ) = &getMacAddr($ipAddr);
    if ( $macType eq "" ) {
      $macAddr = "none";
      $macType = "none";
    }
    $macDispColor = $macColor{ $macType };
    $nodeType = catFileLine("$ipDir/nodetype.txt");
    $manType = catFileLine("$ipDir/managementtype.txt");
    $recType = catFileLine("$ipDir/sipmanrectype.txt");
    my $oidInfo = catFileLine("$ipDir/snmpoid.txt");
    ( $oidName, $rest ) = split(' ', $oidInfo);
    my $firstMac = catFileLine("$ipDir/firstmac.txt");
    $switchPort = getSwitchPort( $macAddr, "html" );
    if ( "$firstMac" ne "" ) {
      $ipIntNo = catFileLine("$macDatabase/$firstMac/ipnetnum.txt");
      $l2IntNo = catFileLine("$macDatabase/$firstMac/intnum.txt");
    }
    if ( $macAddr ne "none" ) {
      my $macInfo = displayOui($macAddr);
      $macAddr = "$macAddr $macInfo";
    }
  }
  my $dnsDispColor = $dnsColor{$dnsType}; if ( "$dnsDispColor" eq "" ) { $dnsDispColor = "white"; }
  if ( "$dnsName" eq "" ) { $dnsName = "none"; }
  my $dispNodeColor = $nodeColor{$nodeType};
  my $dispManColor = $manColor{$manType};
  my $dispRecColor = $recColor{$recType};
  my $netName = &getNetName( $ipAddr, "short", "url");
  my $devName = dispHostName($ipAddr, "return", $dispNodeColor);
  # Simplify color tables based on user setting.
  if ( $SIMparam{'SIMdisplaylessColors'} eq "yes") {
    $macDispColor = $dispNodeColor;
    $dnsDispColor = $dispNodeColor;
  }
  my $info1 = "
          <TD BGCOLOR=$dispManColor ALIGN=center>$manAbrev{ $manType }</TD>
          <TD BGCOLOR=$dispNodeColor>$netName</TD>
          <TD BGCOLOR=$dispNodeColor>$ipAddr</TD>
          <TD BGCOLOR=$macDispColor>$macAddr</TD>
          <TD BGCOLOR=$dispRecColor><FONT COLOR=$recFontColor{ $recType }>$recAbrev{ $recType }</FONT></TD>
	  <TD ALIGN=center BGCOLOR=$dispNodeColor>$nodeType</TD>";
  my $info2 = dispNodeStatus($ipAddr, "return");
  my $info3 = "<TD BGCOLOR=$dnsDispColor ALIGN=right>$dnsName</TD>
          $devName
          <TD BGCOLOR=$dispNodeColor>$oidName</TD>
          <TD BGCOLOR=$dispNodeColor>$ipIntNo/$l2IntNo</TD>
          <TD BGCOLOR=$dispNodeColor>$switchPort</TD>
              ";
  my $cacheInfo = "$ipAddr $macAddr $nodeType $pollStatus $statusTime $dnsName $devName $oidName $ipIntNo $l2IntNo $switchPort\n";
  my $msg = "$info1 $info2 $info3";
  if ( $return eq "return" ) {
    return $msg;
  } else {
    print("<TR BGCOLOR=$dispNodeColor>$msg</TR>");
    return $cacheInfo;
  }
}



1;

